Skip to content

Conversation

@tgymnich
Copy link
Member

No description provided.

@tgymnich tgymnich marked this pull request as ready for review May 23, 2025 17:07
@tgymnich tgymnich requested a review from nikic as a code owner May 23, 2025 17:07
@llvmbot llvmbot added llvm:globalisel llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms llvm:adt labels May 23, 2025
@llvmbot
Copy link
Member

llvmbot commented May 23, 2025

@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-llvm-adt

Author: Tim Gymnich (tgymnich)

Changes

Patch is 48.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141258.diff

14 Files Affected:

  • (removed) llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h (-479)
  • (removed) llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h (-73)
  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+43)
  • (removed) llvm/include/llvm/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.h (-46)
  • (modified) llvm/lib/Analysis/CMakeLists.txt (-1)
  • (removed) llvm/lib/Analysis/FloatingPointPredicateUtils.cpp (-41)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+422-2)
  • (modified) llvm/lib/CodeGen/CodeGenPrepare.cpp (-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/CMakeLists.txt (-1)
  • (removed) llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp (-48)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (-1)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (-1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn (-1)
diff --git a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h b/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
deleted file mode 100644
index 49c5fe0aed6e1..0000000000000
--- a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,479 +0,0 @@
-//===- llvm/Support/GenericFloatingPointPredicateUtils.h -----*- C++-*-----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Utilities for dealing with flags related to floating point properties and
-/// mode controls.
-///
-//===----------------------------------------------------------------------===/
-
-#ifndef LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/FloatingPointMode.h"
-#include "llvm/IR/Instructions.h"
-#include <optional>
-
-namespace llvm {
-
-template <typename ContextT> class GenericFloatingPointPredicateUtils {
-  using ValueRefT = typename ContextT::ValueRefT;
-  using FunctionT = typename ContextT::FunctionT;
-
-  constexpr static ValueRefT Invalid = {};
-
-private:
-  static DenormalMode queryDenormalMode(const FunctionT &F, ValueRefT Val);
-
-  static bool lookThroughFAbs(const FunctionT &F, ValueRefT LHS,
-                              ValueRefT &Src);
-
-  static std::optional<APFloat> matchConstantFloat(const FunctionT &F,
-                                                   ValueRefT Val);
-
-  /// Return the return value for fcmpImpliesClass for a compare that produces
-  /// an exact class test.
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  exactClass(ValueRefT V, FPClassTest M) {
-    return {V, M, ~M};
-  }
-
-public:
-  /// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-  /// same result as an fcmp with the given operands.
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags};
-
-    return fcmpToClassTest(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  const APFloat &ConstRHS, bool LookThroughSrc) {
-
-    auto [Src, ClassIfTrue, ClassIfFalse] =
-        fcmpImpliesClass(Pred, F, LHS, ConstRHS, LookThroughSrc);
-
-    if (Src && ClassIfTrue == ~ClassIfFalse)
-      return {Src, ClassIfTrue};
-
-    return {Invalid, fcAllFlags};
-  }
-
-  /// Compute the possible floating-point classes that \p LHS could be based on
-  /// fcmp \Pred \p LHS, \p RHS.
-  ///
-  /// \returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
-  ///
-  /// If the compare returns an exact class test, ClassesIfTrue ==
-  /// ~ClassesIfFalse
-  ///
-  /// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest will
-  /// only succeed for a test of x > 0 implies positive, but not x > 1).
-  ///
-  /// If \p LookThroughSrc is true, consider the input value when computing the
-  /// mask. This may look through sign bit operations.
-  ///
-  /// If \p LookThroughSrc is false, ignore the source value (i.e. the first
-  /// pair element will always be LHS.
-  ///
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   FPClassTest RHSClass, bool LookThroughSrc) {
-    assert(RHSClass != fcNone);
-    ValueRefT Src = LHS;
-
-    if (Pred == FCmpInst::FCMP_TRUE)
-      return exactClass(Src, fcAllFlags);
-
-    if (Pred == FCmpInst::FCMP_FALSE)
-      return exactClass(Src, fcNone);
-
-    const FPClassTest OrigClass = RHSClass;
-
-    const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass;
-    const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass;
-    const bool IsNaN = (RHSClass & ~fcNan) == fcNone;
-
-    if (IsNaN) {
-      // fcmp o__ x, nan -> false
-      // fcmp u__ x, nan -> true
-      return exactClass(Src, CmpInst::isOrdered(Pred) ? fcNone : fcAllFlags);
-    }
-
-    // fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
-    if (Pred == FCmpInst::FCMP_ORD)
-      return exactClass(Src, ~fcNan);
-
-    // fcmp uno x, zero|normal|subnormal|inf -> fcNan
-    if (Pred == FCmpInst::FCMP_UNO)
-      return exactClass(Src, fcNan);
-
-    const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-    if (IsFabs)
-      RHSClass = llvm::inverse_fabs(RHSClass);
-
-    const bool IsZero = (OrigClass & fcZero) == OrigClass;
-    if (IsZero) {
-      assert(Pred != FCmpInst::FCMP_ORD && Pred != FCmpInst::FCMP_UNO);
-      // Compares with fcNone are only exactly equal to fcZero if input
-      // denormals are not flushed.
-      // TODO: Handle DAZ by expanding masks to cover subnormal cases.
-      DenormalMode Mode = queryDenormalMode(F, LHS);
-      if (Mode.Input != DenormalMode::IEEE)
-        return {Invalid, fcAllFlags, fcAllFlags};
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ: // Match x == 0.0
-        return exactClass(Src, fcZero);
-      case FCmpInst::FCMP_UEQ: // Match isnan(x) || (x == 0.0)
-        return exactClass(Src, fcZero | fcNan);
-      case FCmpInst::FCMP_UNE: // Match (x != 0.0)
-        return exactClass(Src, ~fcZero);
-      case FCmpInst::FCMP_ONE: // Match !isnan(x) && x != 0.0
-        return exactClass(Src, ~fcNan & ~fcZero);
-      case FCmpInst::FCMP_ORD:
-        // Canonical form of ord/uno is with a zero. We could also handle
-        // non-canonical other non-NaN constants or LHS == RHS.
-        return exactClass(Src, ~fcNan);
-      case FCmpInst::FCMP_UNO:
-        return exactClass(Src, fcNan);
-      case FCmpInst::FCMP_OGT: // x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf);
-      case FCmpInst::FCMP_UGT: // isnan(x) || x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan);
-      case FCmpInst::FCMP_OGE: // x >= 0
-        return exactClass(Src, fcPositive | fcNegZero);
-      case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0
-        return exactClass(Src, fcPositive | fcNegZero | fcNan);
-      case FCmpInst::FCMP_OLT: // x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf);
-      case FCmpInst::FCMP_ULT: // isnan(x) || x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan);
-      case FCmpInst::FCMP_OLE: // x <= 0
-        return exactClass(Src, fcNegative | fcPosZero);
-      case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0
-        return exactClass(Src, fcNegative | fcPosZero | fcNan);
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      return {Invalid, fcAllFlags, fcAllFlags};
-    }
-
-    const bool IsDenormalRHS = (OrigClass & fcSubnormal) == OrigClass;
-
-    const bool IsInf = (OrigClass & fcInf) == OrigClass;
-    if (IsInf) {
-      FPClassTest Mask = fcAllFlags;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ:
-      case FCmpInst::FCMP_UNE: {
-        // Match __builtin_isinf patterns
-        //
-        //   fcmp oeq x, +inf -> is_fpclass x, fcPosInf
-        //   fcmp oeq fabs(x), +inf -> is_fpclass x, fcInf
-        //   fcmp oeq x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp oeq fabs(x), -inf -> is_fpclass x, 0 -> false
-        //
-        //   fcmp une x, +inf -> is_fpclass x, ~fcPosInf
-        //   fcmp une fabs(x), +inf -> is_fpclass x, ~fcInf
-        //   fcmp une x, -inf -> is_fpclass x, ~fcNegInf
-        //   fcmp une fabs(x), -inf -> is_fpclass x, fcAllFlags -> true
-        if (IsNegativeRHS) {
-          Mask = fcNegInf;
-          if (IsFabs)
-            Mask = fcNone;
-        } else {
-          Mask = fcPosInf;
-          if (IsFabs)
-            Mask |= fcNegInf;
-        }
-        break;
-      }
-      case FCmpInst::FCMP_ONE:
-      case FCmpInst::FCMP_UEQ: {
-        // Match __builtin_isinf patterns
-        //   fcmp one x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp one fabs(x), -inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one x, +inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one fabs(x), +inf -> is_fpclass x, ~fcInf & fcNan
-        //
-        //   fcmp ueq x, +inf -> is_fpclass x, fcPosInf|fcNan
-        //   fcmp ueq (fabs x), +inf -> is_fpclass x, fcInf|fcNan
-        //   fcmp ueq x, -inf -> is_fpclass x, fcNegInf|fcNan
-        //   fcmp ueq fabs(x), -inf -> is_fpclass x, fcNan
-        if (IsNegativeRHS) {
-          Mask = ~fcNegInf & ~fcNan;
-          if (IsFabs)
-            Mask = ~fcNan;
-        } else {
-          Mask = ~fcPosInf & ~fcNan;
-          if (IsFabs)
-            Mask &= ~fcNegInf;
-        }
-
-        break;
-      }
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        if (IsNegativeRHS) {
-          // No value is ordered and less than negative infinity.
-          // All values are unordered with or at least negative infinity.
-          // fcmp olt x, -inf -> false
-          // fcmp uge x, -inf -> true
-          Mask = fcNone;
-          break;
-        }
-
-        // fcmp olt fabs(x), +inf -> fcFinite
-        // fcmp uge fabs(x), +inf -> ~fcFinite
-        // fcmp olt x, +inf -> fcFinite|fcNegInf
-        // fcmp uge x, +inf -> ~(fcFinite|fcNegInf)
-        Mask = fcFinite;
-        if (!IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        if (IsNegativeRHS) {
-          // fcmp oge x, -inf -> ~fcNan
-          // fcmp oge fabs(x), -inf -> ~fcNan
-          // fcmp ult x, -inf -> fcNan
-          // fcmp ult fabs(x), -inf -> fcNan
-          Mask = ~fcNan;
-          break;
-        }
-
-        // fcmp oge fabs(x), +inf -> fcInf
-        // fcmp oge x, +inf -> fcPosInf
-        // fcmp ult fabs(x), +inf -> ~fcInf
-        // fcmp ult x, +inf -> ~fcPosInf
-        Mask = fcPosInf;
-        if (IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_ULE: {
-        if (IsNegativeRHS) {
-          // fcmp ogt x, -inf -> fcmp one x, -inf
-          // fcmp ogt fabs(x), -inf -> fcmp ord x, x
-          // fcmp ule x, -inf -> fcmp ueq x, -inf
-          // fcmp ule fabs(x), -inf -> fcmp uno x, x
-          Mask = IsFabs ? ~fcNan : ~(fcNegInf | fcNan);
-          break;
-        }
-
-        // No value is ordered and greater than infinity.
-        Mask = fcNone;
-        break;
-      }
-      case FCmpInst::FCMP_OLE:
-      case FCmpInst::FCMP_UGT: {
-        if (IsNegativeRHS) {
-          Mask = IsFabs ? fcNone : fcNegInf;
-          break;
-        }
-
-        // fcmp ole x, +inf -> fcmp ord x, x
-        // fcmp ole fabs(x), +inf -> fcmp ord x, x
-        // fcmp ole x, -inf -> fcmp oeq x, -inf
-        // fcmp ole fabs(x), -inf -> false
-        Mask = ~fcNan;
-        break;
-      }
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    if (Pred == FCmpInst::FCMP_OEQ)
-      return {Src, RHSClass, fcAllFlags};
-
-    if (Pred == FCmpInst::FCMP_UEQ) {
-      FPClassTest Class = RHSClass | fcNan;
-      return {Src, Class, ~fcNan};
-    }
-
-    if (Pred == FCmpInst::FCMP_ONE)
-      return {Src, ~fcNan, RHSClass | fcNan};
-
-    if (Pred == FCmpInst::FCMP_UNE)
-      return {Src, fcAllFlags, RHSClass};
-
-    assert((RHSClass == fcNone || RHSClass == fcPosNormal ||
-            RHSClass == fcNegNormal || RHSClass == fcNormal ||
-            RHSClass == fcPosSubnormal || RHSClass == fcNegSubnormal ||
-            RHSClass == fcSubnormal) &&
-           "should have been recognized as an exact class test");
-
-    if (IsNegativeRHS) {
-      // TODO: Handle fneg(fabs)
-      if (IsFabs) {
-        // fabs(x) o> -k -> fcmp ord x, x
-        // fabs(x) u> -k -> true
-        // fabs(x) o< -k -> false
-        // fabs(x) u< -k -> fcmp uno x, x
-        switch (Pred) {
-        case FCmpInst::FCMP_OGT:
-        case FCmpInst::FCMP_OGE:
-          return {Src, ~fcNan, fcNan};
-        case FCmpInst::FCMP_UGT:
-        case FCmpInst::FCMP_UGE:
-          return {Src, fcAllFlags, fcNone};
-        case FCmpInst::FCMP_OLT:
-        case FCmpInst::FCMP_OLE:
-          return {Src, fcNone, fcAllFlags};
-        case FCmpInst::FCMP_ULT:
-        case FCmpInst::FCMP_ULE:
-          return {Src, fcNan, ~fcNan};
-        default:
-          break;
-        }
-
-        return {Invalid, fcAllFlags, fcAllFlags};
-      }
-
-      FPClassTest ClassesLE = fcNegInf | fcNegNormal;
-      FPClassTest ClassesGE = fcPositive | fcNegZero | fcNegSubnormal;
-
-      if (IsDenormalRHS)
-        ClassesLE |= fcNegSubnormal;
-      else
-        ClassesGE |= fcNegNormal;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    } else if (IsPositiveRHS) {
-      FPClassTest ClassesGE = fcPosNormal | fcPosInf;
-      FPClassTest ClassesLE = fcNegative | fcPosZero | fcPosSubnormal;
-      if (IsDenormalRHS)
-        ClassesGE |= fcPosSubnormal;
-      else
-        ClassesLE |= fcPosNormal;
-
-      if (IsFabs) {
-        ClassesGE = llvm::inverse_fabs(ClassesGE);
-        ClassesLE = llvm::inverse_fabs(ClassesLE);
-      }
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    }
-
-    return {Invalid, fcAllFlags, fcAllFlags};
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   const APFloat &ConstRHS, bool LookThroughSrc) {
-    // We can refine checks against smallest normal / largest denormal to an
-    // exact class test.
-    if (!ConstRHS.isNegative() && ConstRHS.isSmallestNormalized()) {
-      ValueRefT Src = LHS;
-      const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-
-      FPClassTest Mask;
-      // Match pattern that's used in __builtin_isnormal.
-      switch (Pred) {
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        // fcmp olt x, smallest_normal ->
-        // fcNegInf|fcNegNormal|fcSubnormal|fcZero fcmp olt fabs(x),
-        // smallest_normal -> fcSubnormal|fcZero fcmp uge x, smallest_normal ->
-        // fcNan|fcPosNormal|fcPosInf fcmp uge fabs(x), smallest_normal ->
-        // ~(fcSubnormal|fcZero)
-        Mask = fcZero | fcSubnormal;
-        if (!IsFabs)
-          Mask |= fcNegNormal | fcNegInf;
-
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        // fcmp oge x, smallest_normal -> fcPosNormal | fcPosInf
-        // fcmp oge fabs(x), smallest_normal -> fcInf | fcNormal
-        // fcmp ult x, smallest_normal -> ~(fcPosNormal | fcPosInf)
-        // fcmp ult fabs(x), smallest_normal -> ~(fcInf | fcNormal)
-        Mask = fcPosInf | fcPosNormal;
-        if (IsFabs)
-          Mask |= fcNegInf | fcNegNormal;
-        break;
-      }
-      default:
-        return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(),
-                                LookThroughSrc);
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(), LookThroughSrc);
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags, fcAllFlags};
-
-    // TODO: Just call computeKnownFPClass for RHS to handle non-constants.
-    return fcmpImpliesClass(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-};
-
-} // namespace llvm
-
-#endif // LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
diff --git a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h b/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
deleted file mode 100644
index 96fdbf48d8b43..0000000000000
--- a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- llvm/Analysis/FloatingPointPredicateUtils.h ------------*- C++ -*---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/GenericFloatingPointPredicateUtils.h"
-#include "llvm/IR/SSAContext.h"
-
-namespace llvm {
-
-using FloatingPointPredicateUtils =
-    GenericFloatingPointPredicateUtils<SSAContext>;
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                Value *RHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, RHS,
-                                                      LookThroughSrc = true);
-}
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                const APFloat *ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, *ConstRHS,
-                                                      LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 FPClassTest RHSClass, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, RHSClass,
-                                                       LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 const APFloat &ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, Const...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented May 23, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Tim Gymnich (tgymnich)

Changes

Patch is 48.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141258.diff

14 Files Affected:

  • (removed) llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h (-479)
  • (removed) llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h (-73)
  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+43)
  • (removed) llvm/include/llvm/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.h (-46)
  • (modified) llvm/lib/Analysis/CMakeLists.txt (-1)
  • (removed) llvm/lib/Analysis/FloatingPointPredicateUtils.cpp (-41)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+422-2)
  • (modified) llvm/lib/CodeGen/CodeGenPrepare.cpp (-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/CMakeLists.txt (-1)
  • (removed) llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp (-48)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (-1)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (-1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn (-1)
diff --git a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h b/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
deleted file mode 100644
index 49c5fe0aed6e1..0000000000000
--- a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,479 +0,0 @@
-//===- llvm/Support/GenericFloatingPointPredicateUtils.h -----*- C++-*-----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Utilities for dealing with flags related to floating point properties and
-/// mode controls.
-///
-//===----------------------------------------------------------------------===/
-
-#ifndef LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/FloatingPointMode.h"
-#include "llvm/IR/Instructions.h"
-#include <optional>
-
-namespace llvm {
-
-template <typename ContextT> class GenericFloatingPointPredicateUtils {
-  using ValueRefT = typename ContextT::ValueRefT;
-  using FunctionT = typename ContextT::FunctionT;
-
-  constexpr static ValueRefT Invalid = {};
-
-private:
-  static DenormalMode queryDenormalMode(const FunctionT &F, ValueRefT Val);
-
-  static bool lookThroughFAbs(const FunctionT &F, ValueRefT LHS,
-                              ValueRefT &Src);
-
-  static std::optional<APFloat> matchConstantFloat(const FunctionT &F,
-                                                   ValueRefT Val);
-
-  /// Return the return value for fcmpImpliesClass for a compare that produces
-  /// an exact class test.
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  exactClass(ValueRefT V, FPClassTest M) {
-    return {V, M, ~M};
-  }
-
-public:
-  /// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-  /// same result as an fcmp with the given operands.
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags};
-
-    return fcmpToClassTest(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  const APFloat &ConstRHS, bool LookThroughSrc) {
-
-    auto [Src, ClassIfTrue, ClassIfFalse] =
-        fcmpImpliesClass(Pred, F, LHS, ConstRHS, LookThroughSrc);
-
-    if (Src && ClassIfTrue == ~ClassIfFalse)
-      return {Src, ClassIfTrue};
-
-    return {Invalid, fcAllFlags};
-  }
-
-  /// Compute the possible floating-point classes that \p LHS could be based on
-  /// fcmp \Pred \p LHS, \p RHS.
-  ///
-  /// \returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
-  ///
-  /// If the compare returns an exact class test, ClassesIfTrue ==
-  /// ~ClassesIfFalse
-  ///
-  /// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest will
-  /// only succeed for a test of x > 0 implies positive, but not x > 1).
-  ///
-  /// If \p LookThroughSrc is true, consider the input value when computing the
-  /// mask. This may look through sign bit operations.
-  ///
-  /// If \p LookThroughSrc is false, ignore the source value (i.e. the first
-  /// pair element will always be LHS.
-  ///
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   FPClassTest RHSClass, bool LookThroughSrc) {
-    assert(RHSClass != fcNone);
-    ValueRefT Src = LHS;
-
-    if (Pred == FCmpInst::FCMP_TRUE)
-      return exactClass(Src, fcAllFlags);
-
-    if (Pred == FCmpInst::FCMP_FALSE)
-      return exactClass(Src, fcNone);
-
-    const FPClassTest OrigClass = RHSClass;
-
-    const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass;
-    const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass;
-    const bool IsNaN = (RHSClass & ~fcNan) == fcNone;
-
-    if (IsNaN) {
-      // fcmp o__ x, nan -> false
-      // fcmp u__ x, nan -> true
-      return exactClass(Src, CmpInst::isOrdered(Pred) ? fcNone : fcAllFlags);
-    }
-
-    // fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
-    if (Pred == FCmpInst::FCMP_ORD)
-      return exactClass(Src, ~fcNan);
-
-    // fcmp uno x, zero|normal|subnormal|inf -> fcNan
-    if (Pred == FCmpInst::FCMP_UNO)
-      return exactClass(Src, fcNan);
-
-    const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-    if (IsFabs)
-      RHSClass = llvm::inverse_fabs(RHSClass);
-
-    const bool IsZero = (OrigClass & fcZero) == OrigClass;
-    if (IsZero) {
-      assert(Pred != FCmpInst::FCMP_ORD && Pred != FCmpInst::FCMP_UNO);
-      // Compares with fcNone are only exactly equal to fcZero if input
-      // denormals are not flushed.
-      // TODO: Handle DAZ by expanding masks to cover subnormal cases.
-      DenormalMode Mode = queryDenormalMode(F, LHS);
-      if (Mode.Input != DenormalMode::IEEE)
-        return {Invalid, fcAllFlags, fcAllFlags};
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ: // Match x == 0.0
-        return exactClass(Src, fcZero);
-      case FCmpInst::FCMP_UEQ: // Match isnan(x) || (x == 0.0)
-        return exactClass(Src, fcZero | fcNan);
-      case FCmpInst::FCMP_UNE: // Match (x != 0.0)
-        return exactClass(Src, ~fcZero);
-      case FCmpInst::FCMP_ONE: // Match !isnan(x) && x != 0.0
-        return exactClass(Src, ~fcNan & ~fcZero);
-      case FCmpInst::FCMP_ORD:
-        // Canonical form of ord/uno is with a zero. We could also handle
-        // non-canonical other non-NaN constants or LHS == RHS.
-        return exactClass(Src, ~fcNan);
-      case FCmpInst::FCMP_UNO:
-        return exactClass(Src, fcNan);
-      case FCmpInst::FCMP_OGT: // x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf);
-      case FCmpInst::FCMP_UGT: // isnan(x) || x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan);
-      case FCmpInst::FCMP_OGE: // x >= 0
-        return exactClass(Src, fcPositive | fcNegZero);
-      case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0
-        return exactClass(Src, fcPositive | fcNegZero | fcNan);
-      case FCmpInst::FCMP_OLT: // x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf);
-      case FCmpInst::FCMP_ULT: // isnan(x) || x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan);
-      case FCmpInst::FCMP_OLE: // x <= 0
-        return exactClass(Src, fcNegative | fcPosZero);
-      case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0
-        return exactClass(Src, fcNegative | fcPosZero | fcNan);
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      return {Invalid, fcAllFlags, fcAllFlags};
-    }
-
-    const bool IsDenormalRHS = (OrigClass & fcSubnormal) == OrigClass;
-
-    const bool IsInf = (OrigClass & fcInf) == OrigClass;
-    if (IsInf) {
-      FPClassTest Mask = fcAllFlags;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ:
-      case FCmpInst::FCMP_UNE: {
-        // Match __builtin_isinf patterns
-        //
-        //   fcmp oeq x, +inf -> is_fpclass x, fcPosInf
-        //   fcmp oeq fabs(x), +inf -> is_fpclass x, fcInf
-        //   fcmp oeq x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp oeq fabs(x), -inf -> is_fpclass x, 0 -> false
-        //
-        //   fcmp une x, +inf -> is_fpclass x, ~fcPosInf
-        //   fcmp une fabs(x), +inf -> is_fpclass x, ~fcInf
-        //   fcmp une x, -inf -> is_fpclass x, ~fcNegInf
-        //   fcmp une fabs(x), -inf -> is_fpclass x, fcAllFlags -> true
-        if (IsNegativeRHS) {
-          Mask = fcNegInf;
-          if (IsFabs)
-            Mask = fcNone;
-        } else {
-          Mask = fcPosInf;
-          if (IsFabs)
-            Mask |= fcNegInf;
-        }
-        break;
-      }
-      case FCmpInst::FCMP_ONE:
-      case FCmpInst::FCMP_UEQ: {
-        // Match __builtin_isinf patterns
-        //   fcmp one x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp one fabs(x), -inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one x, +inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one fabs(x), +inf -> is_fpclass x, ~fcInf & fcNan
-        //
-        //   fcmp ueq x, +inf -> is_fpclass x, fcPosInf|fcNan
-        //   fcmp ueq (fabs x), +inf -> is_fpclass x, fcInf|fcNan
-        //   fcmp ueq x, -inf -> is_fpclass x, fcNegInf|fcNan
-        //   fcmp ueq fabs(x), -inf -> is_fpclass x, fcNan
-        if (IsNegativeRHS) {
-          Mask = ~fcNegInf & ~fcNan;
-          if (IsFabs)
-            Mask = ~fcNan;
-        } else {
-          Mask = ~fcPosInf & ~fcNan;
-          if (IsFabs)
-            Mask &= ~fcNegInf;
-        }
-
-        break;
-      }
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        if (IsNegativeRHS) {
-          // No value is ordered and less than negative infinity.
-          // All values are unordered with or at least negative infinity.
-          // fcmp olt x, -inf -> false
-          // fcmp uge x, -inf -> true
-          Mask = fcNone;
-          break;
-        }
-
-        // fcmp olt fabs(x), +inf -> fcFinite
-        // fcmp uge fabs(x), +inf -> ~fcFinite
-        // fcmp olt x, +inf -> fcFinite|fcNegInf
-        // fcmp uge x, +inf -> ~(fcFinite|fcNegInf)
-        Mask = fcFinite;
-        if (!IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        if (IsNegativeRHS) {
-          // fcmp oge x, -inf -> ~fcNan
-          // fcmp oge fabs(x), -inf -> ~fcNan
-          // fcmp ult x, -inf -> fcNan
-          // fcmp ult fabs(x), -inf -> fcNan
-          Mask = ~fcNan;
-          break;
-        }
-
-        // fcmp oge fabs(x), +inf -> fcInf
-        // fcmp oge x, +inf -> fcPosInf
-        // fcmp ult fabs(x), +inf -> ~fcInf
-        // fcmp ult x, +inf -> ~fcPosInf
-        Mask = fcPosInf;
-        if (IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_ULE: {
-        if (IsNegativeRHS) {
-          // fcmp ogt x, -inf -> fcmp one x, -inf
-          // fcmp ogt fabs(x), -inf -> fcmp ord x, x
-          // fcmp ule x, -inf -> fcmp ueq x, -inf
-          // fcmp ule fabs(x), -inf -> fcmp uno x, x
-          Mask = IsFabs ? ~fcNan : ~(fcNegInf | fcNan);
-          break;
-        }
-
-        // No value is ordered and greater than infinity.
-        Mask = fcNone;
-        break;
-      }
-      case FCmpInst::FCMP_OLE:
-      case FCmpInst::FCMP_UGT: {
-        if (IsNegativeRHS) {
-          Mask = IsFabs ? fcNone : fcNegInf;
-          break;
-        }
-
-        // fcmp ole x, +inf -> fcmp ord x, x
-        // fcmp ole fabs(x), +inf -> fcmp ord x, x
-        // fcmp ole x, -inf -> fcmp oeq x, -inf
-        // fcmp ole fabs(x), -inf -> false
-        Mask = ~fcNan;
-        break;
-      }
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    if (Pred == FCmpInst::FCMP_OEQ)
-      return {Src, RHSClass, fcAllFlags};
-
-    if (Pred == FCmpInst::FCMP_UEQ) {
-      FPClassTest Class = RHSClass | fcNan;
-      return {Src, Class, ~fcNan};
-    }
-
-    if (Pred == FCmpInst::FCMP_ONE)
-      return {Src, ~fcNan, RHSClass | fcNan};
-
-    if (Pred == FCmpInst::FCMP_UNE)
-      return {Src, fcAllFlags, RHSClass};
-
-    assert((RHSClass == fcNone || RHSClass == fcPosNormal ||
-            RHSClass == fcNegNormal || RHSClass == fcNormal ||
-            RHSClass == fcPosSubnormal || RHSClass == fcNegSubnormal ||
-            RHSClass == fcSubnormal) &&
-           "should have been recognized as an exact class test");
-
-    if (IsNegativeRHS) {
-      // TODO: Handle fneg(fabs)
-      if (IsFabs) {
-        // fabs(x) o> -k -> fcmp ord x, x
-        // fabs(x) u> -k -> true
-        // fabs(x) o< -k -> false
-        // fabs(x) u< -k -> fcmp uno x, x
-        switch (Pred) {
-        case FCmpInst::FCMP_OGT:
-        case FCmpInst::FCMP_OGE:
-          return {Src, ~fcNan, fcNan};
-        case FCmpInst::FCMP_UGT:
-        case FCmpInst::FCMP_UGE:
-          return {Src, fcAllFlags, fcNone};
-        case FCmpInst::FCMP_OLT:
-        case FCmpInst::FCMP_OLE:
-          return {Src, fcNone, fcAllFlags};
-        case FCmpInst::FCMP_ULT:
-        case FCmpInst::FCMP_ULE:
-          return {Src, fcNan, ~fcNan};
-        default:
-          break;
-        }
-
-        return {Invalid, fcAllFlags, fcAllFlags};
-      }
-
-      FPClassTest ClassesLE = fcNegInf | fcNegNormal;
-      FPClassTest ClassesGE = fcPositive | fcNegZero | fcNegSubnormal;
-
-      if (IsDenormalRHS)
-        ClassesLE |= fcNegSubnormal;
-      else
-        ClassesGE |= fcNegNormal;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    } else if (IsPositiveRHS) {
-      FPClassTest ClassesGE = fcPosNormal | fcPosInf;
-      FPClassTest ClassesLE = fcNegative | fcPosZero | fcPosSubnormal;
-      if (IsDenormalRHS)
-        ClassesGE |= fcPosSubnormal;
-      else
-        ClassesLE |= fcPosNormal;
-
-      if (IsFabs) {
-        ClassesGE = llvm::inverse_fabs(ClassesGE);
-        ClassesLE = llvm::inverse_fabs(ClassesLE);
-      }
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    }
-
-    return {Invalid, fcAllFlags, fcAllFlags};
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   const APFloat &ConstRHS, bool LookThroughSrc) {
-    // We can refine checks against smallest normal / largest denormal to an
-    // exact class test.
-    if (!ConstRHS.isNegative() && ConstRHS.isSmallestNormalized()) {
-      ValueRefT Src = LHS;
-      const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-
-      FPClassTest Mask;
-      // Match pattern that's used in __builtin_isnormal.
-      switch (Pred) {
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        // fcmp olt x, smallest_normal ->
-        // fcNegInf|fcNegNormal|fcSubnormal|fcZero fcmp olt fabs(x),
-        // smallest_normal -> fcSubnormal|fcZero fcmp uge x, smallest_normal ->
-        // fcNan|fcPosNormal|fcPosInf fcmp uge fabs(x), smallest_normal ->
-        // ~(fcSubnormal|fcZero)
-        Mask = fcZero | fcSubnormal;
-        if (!IsFabs)
-          Mask |= fcNegNormal | fcNegInf;
-
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        // fcmp oge x, smallest_normal -> fcPosNormal | fcPosInf
-        // fcmp oge fabs(x), smallest_normal -> fcInf | fcNormal
-        // fcmp ult x, smallest_normal -> ~(fcPosNormal | fcPosInf)
-        // fcmp ult fabs(x), smallest_normal -> ~(fcInf | fcNormal)
-        Mask = fcPosInf | fcPosNormal;
-        if (IsFabs)
-          Mask |= fcNegInf | fcNegNormal;
-        break;
-      }
-      default:
-        return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(),
-                                LookThroughSrc);
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(), LookThroughSrc);
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags, fcAllFlags};
-
-    // TODO: Just call computeKnownFPClass for RHS to handle non-constants.
-    return fcmpImpliesClass(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-};
-
-} // namespace llvm
-
-#endif // LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
diff --git a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h b/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
deleted file mode 100644
index 96fdbf48d8b43..0000000000000
--- a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- llvm/Analysis/FloatingPointPredicateUtils.h ------------*- C++ -*---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/GenericFloatingPointPredicateUtils.h"
-#include "llvm/IR/SSAContext.h"
-
-namespace llvm {
-
-using FloatingPointPredicateUtils =
-    GenericFloatingPointPredicateUtils<SSAContext>;
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                Value *RHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, RHS,
-                                                      LookThroughSrc = true);
-}
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                const APFloat *ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, *ConstRHS,
-                                                      LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 FPClassTest RHSClass, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, RHSClass,
-                                                       LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 const APFloat &ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, Const...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented May 23, 2025

@llvm/pr-subscribers-llvm-analysis

Author: Tim Gymnich (tgymnich)

Changes

Patch is 48.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141258.diff

14 Files Affected:

  • (removed) llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h (-479)
  • (removed) llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h (-73)
  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+43)
  • (removed) llvm/include/llvm/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.h (-46)
  • (modified) llvm/lib/Analysis/CMakeLists.txt (-1)
  • (removed) llvm/lib/Analysis/FloatingPointPredicateUtils.cpp (-41)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+422-2)
  • (modified) llvm/lib/CodeGen/CodeGenPrepare.cpp (-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/CMakeLists.txt (-1)
  • (removed) llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp (-48)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (-1)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (-1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn (-1)
diff --git a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h b/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
deleted file mode 100644
index 49c5fe0aed6e1..0000000000000
--- a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,479 +0,0 @@
-//===- llvm/Support/GenericFloatingPointPredicateUtils.h -----*- C++-*-----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Utilities for dealing with flags related to floating point properties and
-/// mode controls.
-///
-//===----------------------------------------------------------------------===/
-
-#ifndef LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/FloatingPointMode.h"
-#include "llvm/IR/Instructions.h"
-#include <optional>
-
-namespace llvm {
-
-template <typename ContextT> class GenericFloatingPointPredicateUtils {
-  using ValueRefT = typename ContextT::ValueRefT;
-  using FunctionT = typename ContextT::FunctionT;
-
-  constexpr static ValueRefT Invalid = {};
-
-private:
-  static DenormalMode queryDenormalMode(const FunctionT &F, ValueRefT Val);
-
-  static bool lookThroughFAbs(const FunctionT &F, ValueRefT LHS,
-                              ValueRefT &Src);
-
-  static std::optional<APFloat> matchConstantFloat(const FunctionT &F,
-                                                   ValueRefT Val);
-
-  /// Return the return value for fcmpImpliesClass for a compare that produces
-  /// an exact class test.
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  exactClass(ValueRefT V, FPClassTest M) {
-    return {V, M, ~M};
-  }
-
-public:
-  /// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-  /// same result as an fcmp with the given operands.
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags};
-
-    return fcmpToClassTest(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  const APFloat &ConstRHS, bool LookThroughSrc) {
-
-    auto [Src, ClassIfTrue, ClassIfFalse] =
-        fcmpImpliesClass(Pred, F, LHS, ConstRHS, LookThroughSrc);
-
-    if (Src && ClassIfTrue == ~ClassIfFalse)
-      return {Src, ClassIfTrue};
-
-    return {Invalid, fcAllFlags};
-  }
-
-  /// Compute the possible floating-point classes that \p LHS could be based on
-  /// fcmp \Pred \p LHS, \p RHS.
-  ///
-  /// \returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
-  ///
-  /// If the compare returns an exact class test, ClassesIfTrue ==
-  /// ~ClassesIfFalse
-  ///
-  /// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest will
-  /// only succeed for a test of x > 0 implies positive, but not x > 1).
-  ///
-  /// If \p LookThroughSrc is true, consider the input value when computing the
-  /// mask. This may look through sign bit operations.
-  ///
-  /// If \p LookThroughSrc is false, ignore the source value (i.e. the first
-  /// pair element will always be LHS.
-  ///
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   FPClassTest RHSClass, bool LookThroughSrc) {
-    assert(RHSClass != fcNone);
-    ValueRefT Src = LHS;
-
-    if (Pred == FCmpInst::FCMP_TRUE)
-      return exactClass(Src, fcAllFlags);
-
-    if (Pred == FCmpInst::FCMP_FALSE)
-      return exactClass(Src, fcNone);
-
-    const FPClassTest OrigClass = RHSClass;
-
-    const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass;
-    const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass;
-    const bool IsNaN = (RHSClass & ~fcNan) == fcNone;
-
-    if (IsNaN) {
-      // fcmp o__ x, nan -> false
-      // fcmp u__ x, nan -> true
-      return exactClass(Src, CmpInst::isOrdered(Pred) ? fcNone : fcAllFlags);
-    }
-
-    // fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
-    if (Pred == FCmpInst::FCMP_ORD)
-      return exactClass(Src, ~fcNan);
-
-    // fcmp uno x, zero|normal|subnormal|inf -> fcNan
-    if (Pred == FCmpInst::FCMP_UNO)
-      return exactClass(Src, fcNan);
-
-    const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-    if (IsFabs)
-      RHSClass = llvm::inverse_fabs(RHSClass);
-
-    const bool IsZero = (OrigClass & fcZero) == OrigClass;
-    if (IsZero) {
-      assert(Pred != FCmpInst::FCMP_ORD && Pred != FCmpInst::FCMP_UNO);
-      // Compares with fcNone are only exactly equal to fcZero if input
-      // denormals are not flushed.
-      // TODO: Handle DAZ by expanding masks to cover subnormal cases.
-      DenormalMode Mode = queryDenormalMode(F, LHS);
-      if (Mode.Input != DenormalMode::IEEE)
-        return {Invalid, fcAllFlags, fcAllFlags};
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ: // Match x == 0.0
-        return exactClass(Src, fcZero);
-      case FCmpInst::FCMP_UEQ: // Match isnan(x) || (x == 0.0)
-        return exactClass(Src, fcZero | fcNan);
-      case FCmpInst::FCMP_UNE: // Match (x != 0.0)
-        return exactClass(Src, ~fcZero);
-      case FCmpInst::FCMP_ONE: // Match !isnan(x) && x != 0.0
-        return exactClass(Src, ~fcNan & ~fcZero);
-      case FCmpInst::FCMP_ORD:
-        // Canonical form of ord/uno is with a zero. We could also handle
-        // non-canonical other non-NaN constants or LHS == RHS.
-        return exactClass(Src, ~fcNan);
-      case FCmpInst::FCMP_UNO:
-        return exactClass(Src, fcNan);
-      case FCmpInst::FCMP_OGT: // x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf);
-      case FCmpInst::FCMP_UGT: // isnan(x) || x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan);
-      case FCmpInst::FCMP_OGE: // x >= 0
-        return exactClass(Src, fcPositive | fcNegZero);
-      case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0
-        return exactClass(Src, fcPositive | fcNegZero | fcNan);
-      case FCmpInst::FCMP_OLT: // x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf);
-      case FCmpInst::FCMP_ULT: // isnan(x) || x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan);
-      case FCmpInst::FCMP_OLE: // x <= 0
-        return exactClass(Src, fcNegative | fcPosZero);
-      case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0
-        return exactClass(Src, fcNegative | fcPosZero | fcNan);
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      return {Invalid, fcAllFlags, fcAllFlags};
-    }
-
-    const bool IsDenormalRHS = (OrigClass & fcSubnormal) == OrigClass;
-
-    const bool IsInf = (OrigClass & fcInf) == OrigClass;
-    if (IsInf) {
-      FPClassTest Mask = fcAllFlags;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ:
-      case FCmpInst::FCMP_UNE: {
-        // Match __builtin_isinf patterns
-        //
-        //   fcmp oeq x, +inf -> is_fpclass x, fcPosInf
-        //   fcmp oeq fabs(x), +inf -> is_fpclass x, fcInf
-        //   fcmp oeq x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp oeq fabs(x), -inf -> is_fpclass x, 0 -> false
-        //
-        //   fcmp une x, +inf -> is_fpclass x, ~fcPosInf
-        //   fcmp une fabs(x), +inf -> is_fpclass x, ~fcInf
-        //   fcmp une x, -inf -> is_fpclass x, ~fcNegInf
-        //   fcmp une fabs(x), -inf -> is_fpclass x, fcAllFlags -> true
-        if (IsNegativeRHS) {
-          Mask = fcNegInf;
-          if (IsFabs)
-            Mask = fcNone;
-        } else {
-          Mask = fcPosInf;
-          if (IsFabs)
-            Mask |= fcNegInf;
-        }
-        break;
-      }
-      case FCmpInst::FCMP_ONE:
-      case FCmpInst::FCMP_UEQ: {
-        // Match __builtin_isinf patterns
-        //   fcmp one x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp one fabs(x), -inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one x, +inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one fabs(x), +inf -> is_fpclass x, ~fcInf & fcNan
-        //
-        //   fcmp ueq x, +inf -> is_fpclass x, fcPosInf|fcNan
-        //   fcmp ueq (fabs x), +inf -> is_fpclass x, fcInf|fcNan
-        //   fcmp ueq x, -inf -> is_fpclass x, fcNegInf|fcNan
-        //   fcmp ueq fabs(x), -inf -> is_fpclass x, fcNan
-        if (IsNegativeRHS) {
-          Mask = ~fcNegInf & ~fcNan;
-          if (IsFabs)
-            Mask = ~fcNan;
-        } else {
-          Mask = ~fcPosInf & ~fcNan;
-          if (IsFabs)
-            Mask &= ~fcNegInf;
-        }
-
-        break;
-      }
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        if (IsNegativeRHS) {
-          // No value is ordered and less than negative infinity.
-          // All values are unordered with or at least negative infinity.
-          // fcmp olt x, -inf -> false
-          // fcmp uge x, -inf -> true
-          Mask = fcNone;
-          break;
-        }
-
-        // fcmp olt fabs(x), +inf -> fcFinite
-        // fcmp uge fabs(x), +inf -> ~fcFinite
-        // fcmp olt x, +inf -> fcFinite|fcNegInf
-        // fcmp uge x, +inf -> ~(fcFinite|fcNegInf)
-        Mask = fcFinite;
-        if (!IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        if (IsNegativeRHS) {
-          // fcmp oge x, -inf -> ~fcNan
-          // fcmp oge fabs(x), -inf -> ~fcNan
-          // fcmp ult x, -inf -> fcNan
-          // fcmp ult fabs(x), -inf -> fcNan
-          Mask = ~fcNan;
-          break;
-        }
-
-        // fcmp oge fabs(x), +inf -> fcInf
-        // fcmp oge x, +inf -> fcPosInf
-        // fcmp ult fabs(x), +inf -> ~fcInf
-        // fcmp ult x, +inf -> ~fcPosInf
-        Mask = fcPosInf;
-        if (IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_ULE: {
-        if (IsNegativeRHS) {
-          // fcmp ogt x, -inf -> fcmp one x, -inf
-          // fcmp ogt fabs(x), -inf -> fcmp ord x, x
-          // fcmp ule x, -inf -> fcmp ueq x, -inf
-          // fcmp ule fabs(x), -inf -> fcmp uno x, x
-          Mask = IsFabs ? ~fcNan : ~(fcNegInf | fcNan);
-          break;
-        }
-
-        // No value is ordered and greater than infinity.
-        Mask = fcNone;
-        break;
-      }
-      case FCmpInst::FCMP_OLE:
-      case FCmpInst::FCMP_UGT: {
-        if (IsNegativeRHS) {
-          Mask = IsFabs ? fcNone : fcNegInf;
-          break;
-        }
-
-        // fcmp ole x, +inf -> fcmp ord x, x
-        // fcmp ole fabs(x), +inf -> fcmp ord x, x
-        // fcmp ole x, -inf -> fcmp oeq x, -inf
-        // fcmp ole fabs(x), -inf -> false
-        Mask = ~fcNan;
-        break;
-      }
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    if (Pred == FCmpInst::FCMP_OEQ)
-      return {Src, RHSClass, fcAllFlags};
-
-    if (Pred == FCmpInst::FCMP_UEQ) {
-      FPClassTest Class = RHSClass | fcNan;
-      return {Src, Class, ~fcNan};
-    }
-
-    if (Pred == FCmpInst::FCMP_ONE)
-      return {Src, ~fcNan, RHSClass | fcNan};
-
-    if (Pred == FCmpInst::FCMP_UNE)
-      return {Src, fcAllFlags, RHSClass};
-
-    assert((RHSClass == fcNone || RHSClass == fcPosNormal ||
-            RHSClass == fcNegNormal || RHSClass == fcNormal ||
-            RHSClass == fcPosSubnormal || RHSClass == fcNegSubnormal ||
-            RHSClass == fcSubnormal) &&
-           "should have been recognized as an exact class test");
-
-    if (IsNegativeRHS) {
-      // TODO: Handle fneg(fabs)
-      if (IsFabs) {
-        // fabs(x) o> -k -> fcmp ord x, x
-        // fabs(x) u> -k -> true
-        // fabs(x) o< -k -> false
-        // fabs(x) u< -k -> fcmp uno x, x
-        switch (Pred) {
-        case FCmpInst::FCMP_OGT:
-        case FCmpInst::FCMP_OGE:
-          return {Src, ~fcNan, fcNan};
-        case FCmpInst::FCMP_UGT:
-        case FCmpInst::FCMP_UGE:
-          return {Src, fcAllFlags, fcNone};
-        case FCmpInst::FCMP_OLT:
-        case FCmpInst::FCMP_OLE:
-          return {Src, fcNone, fcAllFlags};
-        case FCmpInst::FCMP_ULT:
-        case FCmpInst::FCMP_ULE:
-          return {Src, fcNan, ~fcNan};
-        default:
-          break;
-        }
-
-        return {Invalid, fcAllFlags, fcAllFlags};
-      }
-
-      FPClassTest ClassesLE = fcNegInf | fcNegNormal;
-      FPClassTest ClassesGE = fcPositive | fcNegZero | fcNegSubnormal;
-
-      if (IsDenormalRHS)
-        ClassesLE |= fcNegSubnormal;
-      else
-        ClassesGE |= fcNegNormal;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    } else if (IsPositiveRHS) {
-      FPClassTest ClassesGE = fcPosNormal | fcPosInf;
-      FPClassTest ClassesLE = fcNegative | fcPosZero | fcPosSubnormal;
-      if (IsDenormalRHS)
-        ClassesGE |= fcPosSubnormal;
-      else
-        ClassesLE |= fcPosNormal;
-
-      if (IsFabs) {
-        ClassesGE = llvm::inverse_fabs(ClassesGE);
-        ClassesLE = llvm::inverse_fabs(ClassesLE);
-      }
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    }
-
-    return {Invalid, fcAllFlags, fcAllFlags};
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   const APFloat &ConstRHS, bool LookThroughSrc) {
-    // We can refine checks against smallest normal / largest denormal to an
-    // exact class test.
-    if (!ConstRHS.isNegative() && ConstRHS.isSmallestNormalized()) {
-      ValueRefT Src = LHS;
-      const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-
-      FPClassTest Mask;
-      // Match pattern that's used in __builtin_isnormal.
-      switch (Pred) {
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        // fcmp olt x, smallest_normal ->
-        // fcNegInf|fcNegNormal|fcSubnormal|fcZero fcmp olt fabs(x),
-        // smallest_normal -> fcSubnormal|fcZero fcmp uge x, smallest_normal ->
-        // fcNan|fcPosNormal|fcPosInf fcmp uge fabs(x), smallest_normal ->
-        // ~(fcSubnormal|fcZero)
-        Mask = fcZero | fcSubnormal;
-        if (!IsFabs)
-          Mask |= fcNegNormal | fcNegInf;
-
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        // fcmp oge x, smallest_normal -> fcPosNormal | fcPosInf
-        // fcmp oge fabs(x), smallest_normal -> fcInf | fcNormal
-        // fcmp ult x, smallest_normal -> ~(fcPosNormal | fcPosInf)
-        // fcmp ult fabs(x), smallest_normal -> ~(fcInf | fcNormal)
-        Mask = fcPosInf | fcPosNormal;
-        if (IsFabs)
-          Mask |= fcNegInf | fcNegNormal;
-        break;
-      }
-      default:
-        return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(),
-                                LookThroughSrc);
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(), LookThroughSrc);
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags, fcAllFlags};
-
-    // TODO: Just call computeKnownFPClass for RHS to handle non-constants.
-    return fcmpImpliesClass(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-};
-
-} // namespace llvm
-
-#endif // LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
diff --git a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h b/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
deleted file mode 100644
index 96fdbf48d8b43..0000000000000
--- a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- llvm/Analysis/FloatingPointPredicateUtils.h ------------*- C++ -*---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/GenericFloatingPointPredicateUtils.h"
-#include "llvm/IR/SSAContext.h"
-
-namespace llvm {
-
-using FloatingPointPredicateUtils =
-    GenericFloatingPointPredicateUtils<SSAContext>;
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                Value *RHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, RHS,
-                                                      LookThroughSrc = true);
-}
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                const APFloat *ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, *ConstRHS,
-                                                      LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 FPClassTest RHSClass, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, RHSClass,
-                                                       LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 const APFloat &ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, Const...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented May 23, 2025

@llvm/pr-subscribers-llvm-globalisel

Author: Tim Gymnich (tgymnich)

Changes

Patch is 48.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141258.diff

14 Files Affected:

  • (removed) llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h (-479)
  • (removed) llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h (-73)
  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+43)
  • (removed) llvm/include/llvm/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.h (-46)
  • (modified) llvm/lib/Analysis/CMakeLists.txt (-1)
  • (removed) llvm/lib/Analysis/FloatingPointPredicateUtils.cpp (-41)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (-1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+422-2)
  • (modified) llvm/lib/CodeGen/CodeGenPrepare.cpp (-1)
  • (modified) llvm/lib/CodeGen/GlobalISel/CMakeLists.txt (-1)
  • (removed) llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp (-48)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (-1)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (-1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn (-1)
diff --git a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h b/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
deleted file mode 100644
index 49c5fe0aed6e1..0000000000000
--- a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,479 +0,0 @@
-//===- llvm/Support/GenericFloatingPointPredicateUtils.h -----*- C++-*-----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Utilities for dealing with flags related to floating point properties and
-/// mode controls.
-///
-//===----------------------------------------------------------------------===/
-
-#ifndef LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/FloatingPointMode.h"
-#include "llvm/IR/Instructions.h"
-#include <optional>
-
-namespace llvm {
-
-template <typename ContextT> class GenericFloatingPointPredicateUtils {
-  using ValueRefT = typename ContextT::ValueRefT;
-  using FunctionT = typename ContextT::FunctionT;
-
-  constexpr static ValueRefT Invalid = {};
-
-private:
-  static DenormalMode queryDenormalMode(const FunctionT &F, ValueRefT Val);
-
-  static bool lookThroughFAbs(const FunctionT &F, ValueRefT LHS,
-                              ValueRefT &Src);
-
-  static std::optional<APFloat> matchConstantFloat(const FunctionT &F,
-                                                   ValueRefT Val);
-
-  /// Return the return value for fcmpImpliesClass for a compare that produces
-  /// an exact class test.
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  exactClass(ValueRefT V, FPClassTest M) {
-    return {V, M, ~M};
-  }
-
-public:
-  /// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-  /// same result as an fcmp with the given operands.
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags};
-
-    return fcmpToClassTest(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-
-  static std::pair<ValueRefT, FPClassTest>
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                  const APFloat &ConstRHS, bool LookThroughSrc) {
-
-    auto [Src, ClassIfTrue, ClassIfFalse] =
-        fcmpImpliesClass(Pred, F, LHS, ConstRHS, LookThroughSrc);
-
-    if (Src && ClassIfTrue == ~ClassIfFalse)
-      return {Src, ClassIfTrue};
-
-    return {Invalid, fcAllFlags};
-  }
-
-  /// Compute the possible floating-point classes that \p LHS could be based on
-  /// fcmp \Pred \p LHS, \p RHS.
-  ///
-  /// \returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
-  ///
-  /// If the compare returns an exact class test, ClassesIfTrue ==
-  /// ~ClassesIfFalse
-  ///
-  /// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest will
-  /// only succeed for a test of x > 0 implies positive, but not x > 1).
-  ///
-  /// If \p LookThroughSrc is true, consider the input value when computing the
-  /// mask. This may look through sign bit operations.
-  ///
-  /// If \p LookThroughSrc is false, ignore the source value (i.e. the first
-  /// pair element will always be LHS.
-  ///
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   FPClassTest RHSClass, bool LookThroughSrc) {
-    assert(RHSClass != fcNone);
-    ValueRefT Src = LHS;
-
-    if (Pred == FCmpInst::FCMP_TRUE)
-      return exactClass(Src, fcAllFlags);
-
-    if (Pred == FCmpInst::FCMP_FALSE)
-      return exactClass(Src, fcNone);
-
-    const FPClassTest OrigClass = RHSClass;
-
-    const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass;
-    const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass;
-    const bool IsNaN = (RHSClass & ~fcNan) == fcNone;
-
-    if (IsNaN) {
-      // fcmp o__ x, nan -> false
-      // fcmp u__ x, nan -> true
-      return exactClass(Src, CmpInst::isOrdered(Pred) ? fcNone : fcAllFlags);
-    }
-
-    // fcmp ord x, zero|normal|subnormal|inf -> ~fcNan
-    if (Pred == FCmpInst::FCMP_ORD)
-      return exactClass(Src, ~fcNan);
-
-    // fcmp uno x, zero|normal|subnormal|inf -> fcNan
-    if (Pred == FCmpInst::FCMP_UNO)
-      return exactClass(Src, fcNan);
-
-    const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-    if (IsFabs)
-      RHSClass = llvm::inverse_fabs(RHSClass);
-
-    const bool IsZero = (OrigClass & fcZero) == OrigClass;
-    if (IsZero) {
-      assert(Pred != FCmpInst::FCMP_ORD && Pred != FCmpInst::FCMP_UNO);
-      // Compares with fcNone are only exactly equal to fcZero if input
-      // denormals are not flushed.
-      // TODO: Handle DAZ by expanding masks to cover subnormal cases.
-      DenormalMode Mode = queryDenormalMode(F, LHS);
-      if (Mode.Input != DenormalMode::IEEE)
-        return {Invalid, fcAllFlags, fcAllFlags};
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ: // Match x == 0.0
-        return exactClass(Src, fcZero);
-      case FCmpInst::FCMP_UEQ: // Match isnan(x) || (x == 0.0)
-        return exactClass(Src, fcZero | fcNan);
-      case FCmpInst::FCMP_UNE: // Match (x != 0.0)
-        return exactClass(Src, ~fcZero);
-      case FCmpInst::FCMP_ONE: // Match !isnan(x) && x != 0.0
-        return exactClass(Src, ~fcNan & ~fcZero);
-      case FCmpInst::FCMP_ORD:
-        // Canonical form of ord/uno is with a zero. We could also handle
-        // non-canonical other non-NaN constants or LHS == RHS.
-        return exactClass(Src, ~fcNan);
-      case FCmpInst::FCMP_UNO:
-        return exactClass(Src, fcNan);
-      case FCmpInst::FCMP_OGT: // x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf);
-      case FCmpInst::FCMP_UGT: // isnan(x) || x > 0
-        return exactClass(Src, fcPosSubnormal | fcPosNormal | fcPosInf | fcNan);
-      case FCmpInst::FCMP_OGE: // x >= 0
-        return exactClass(Src, fcPositive | fcNegZero);
-      case FCmpInst::FCMP_UGE: // isnan(x) || x >= 0
-        return exactClass(Src, fcPositive | fcNegZero | fcNan);
-      case FCmpInst::FCMP_OLT: // x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf);
-      case FCmpInst::FCMP_ULT: // isnan(x) || x < 0
-        return exactClass(Src, fcNegSubnormal | fcNegNormal | fcNegInf | fcNan);
-      case FCmpInst::FCMP_OLE: // x <= 0
-        return exactClass(Src, fcNegative | fcPosZero);
-      case FCmpInst::FCMP_ULE: // isnan(x) || x <= 0
-        return exactClass(Src, fcNegative | fcPosZero | fcNan);
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      return {Invalid, fcAllFlags, fcAllFlags};
-    }
-
-    const bool IsDenormalRHS = (OrigClass & fcSubnormal) == OrigClass;
-
-    const bool IsInf = (OrigClass & fcInf) == OrigClass;
-    if (IsInf) {
-      FPClassTest Mask = fcAllFlags;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OEQ:
-      case FCmpInst::FCMP_UNE: {
-        // Match __builtin_isinf patterns
-        //
-        //   fcmp oeq x, +inf -> is_fpclass x, fcPosInf
-        //   fcmp oeq fabs(x), +inf -> is_fpclass x, fcInf
-        //   fcmp oeq x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp oeq fabs(x), -inf -> is_fpclass x, 0 -> false
-        //
-        //   fcmp une x, +inf -> is_fpclass x, ~fcPosInf
-        //   fcmp une fabs(x), +inf -> is_fpclass x, ~fcInf
-        //   fcmp une x, -inf -> is_fpclass x, ~fcNegInf
-        //   fcmp une fabs(x), -inf -> is_fpclass x, fcAllFlags -> true
-        if (IsNegativeRHS) {
-          Mask = fcNegInf;
-          if (IsFabs)
-            Mask = fcNone;
-        } else {
-          Mask = fcPosInf;
-          if (IsFabs)
-            Mask |= fcNegInf;
-        }
-        break;
-      }
-      case FCmpInst::FCMP_ONE:
-      case FCmpInst::FCMP_UEQ: {
-        // Match __builtin_isinf patterns
-        //   fcmp one x, -inf -> is_fpclass x, fcNegInf
-        //   fcmp one fabs(x), -inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one x, +inf -> is_fpclass x, ~fcNegInf & ~fcNan
-        //   fcmp one fabs(x), +inf -> is_fpclass x, ~fcInf & fcNan
-        //
-        //   fcmp ueq x, +inf -> is_fpclass x, fcPosInf|fcNan
-        //   fcmp ueq (fabs x), +inf -> is_fpclass x, fcInf|fcNan
-        //   fcmp ueq x, -inf -> is_fpclass x, fcNegInf|fcNan
-        //   fcmp ueq fabs(x), -inf -> is_fpclass x, fcNan
-        if (IsNegativeRHS) {
-          Mask = ~fcNegInf & ~fcNan;
-          if (IsFabs)
-            Mask = ~fcNan;
-        } else {
-          Mask = ~fcPosInf & ~fcNan;
-          if (IsFabs)
-            Mask &= ~fcNegInf;
-        }
-
-        break;
-      }
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        if (IsNegativeRHS) {
-          // No value is ordered and less than negative infinity.
-          // All values are unordered with or at least negative infinity.
-          // fcmp olt x, -inf -> false
-          // fcmp uge x, -inf -> true
-          Mask = fcNone;
-          break;
-        }
-
-        // fcmp olt fabs(x), +inf -> fcFinite
-        // fcmp uge fabs(x), +inf -> ~fcFinite
-        // fcmp olt x, +inf -> fcFinite|fcNegInf
-        // fcmp uge x, +inf -> ~(fcFinite|fcNegInf)
-        Mask = fcFinite;
-        if (!IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        if (IsNegativeRHS) {
-          // fcmp oge x, -inf -> ~fcNan
-          // fcmp oge fabs(x), -inf -> ~fcNan
-          // fcmp ult x, -inf -> fcNan
-          // fcmp ult fabs(x), -inf -> fcNan
-          Mask = ~fcNan;
-          break;
-        }
-
-        // fcmp oge fabs(x), +inf -> fcInf
-        // fcmp oge x, +inf -> fcPosInf
-        // fcmp ult fabs(x), +inf -> ~fcInf
-        // fcmp ult x, +inf -> ~fcPosInf
-        Mask = fcPosInf;
-        if (IsFabs)
-          Mask |= fcNegInf;
-        break;
-      }
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_ULE: {
-        if (IsNegativeRHS) {
-          // fcmp ogt x, -inf -> fcmp one x, -inf
-          // fcmp ogt fabs(x), -inf -> fcmp ord x, x
-          // fcmp ule x, -inf -> fcmp ueq x, -inf
-          // fcmp ule fabs(x), -inf -> fcmp uno x, x
-          Mask = IsFabs ? ~fcNan : ~(fcNegInf | fcNan);
-          break;
-        }
-
-        // No value is ordered and greater than infinity.
-        Mask = fcNone;
-        break;
-      }
-      case FCmpInst::FCMP_OLE:
-      case FCmpInst::FCMP_UGT: {
-        if (IsNegativeRHS) {
-          Mask = IsFabs ? fcNone : fcNegInf;
-          break;
-        }
-
-        // fcmp ole x, +inf -> fcmp ord x, x
-        // fcmp ole fabs(x), +inf -> fcmp ord x, x
-        // fcmp ole x, -inf -> fcmp oeq x, -inf
-        // fcmp ole fabs(x), -inf -> false
-        Mask = ~fcNan;
-        break;
-      }
-      default:
-        llvm_unreachable("all compare types are handled");
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    if (Pred == FCmpInst::FCMP_OEQ)
-      return {Src, RHSClass, fcAllFlags};
-
-    if (Pred == FCmpInst::FCMP_UEQ) {
-      FPClassTest Class = RHSClass | fcNan;
-      return {Src, Class, ~fcNan};
-    }
-
-    if (Pred == FCmpInst::FCMP_ONE)
-      return {Src, ~fcNan, RHSClass | fcNan};
-
-    if (Pred == FCmpInst::FCMP_UNE)
-      return {Src, fcAllFlags, RHSClass};
-
-    assert((RHSClass == fcNone || RHSClass == fcPosNormal ||
-            RHSClass == fcNegNormal || RHSClass == fcNormal ||
-            RHSClass == fcPosSubnormal || RHSClass == fcNegSubnormal ||
-            RHSClass == fcSubnormal) &&
-           "should have been recognized as an exact class test");
-
-    if (IsNegativeRHS) {
-      // TODO: Handle fneg(fabs)
-      if (IsFabs) {
-        // fabs(x) o> -k -> fcmp ord x, x
-        // fabs(x) u> -k -> true
-        // fabs(x) o< -k -> false
-        // fabs(x) u< -k -> fcmp uno x, x
-        switch (Pred) {
-        case FCmpInst::FCMP_OGT:
-        case FCmpInst::FCMP_OGE:
-          return {Src, ~fcNan, fcNan};
-        case FCmpInst::FCMP_UGT:
-        case FCmpInst::FCMP_UGE:
-          return {Src, fcAllFlags, fcNone};
-        case FCmpInst::FCMP_OLT:
-        case FCmpInst::FCMP_OLE:
-          return {Src, fcNone, fcAllFlags};
-        case FCmpInst::FCMP_ULT:
-        case FCmpInst::FCMP_ULE:
-          return {Src, fcNan, ~fcNan};
-        default:
-          break;
-        }
-
-        return {Invalid, fcAllFlags, fcAllFlags};
-      }
-
-      FPClassTest ClassesLE = fcNegInf | fcNegNormal;
-      FPClassTest ClassesGE = fcPositive | fcNegZero | fcNegSubnormal;
-
-      if (IsDenormalRHS)
-        ClassesLE |= fcNegSubnormal;
-      else
-        ClassesGE |= fcNegNormal;
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    } else if (IsPositiveRHS) {
-      FPClassTest ClassesGE = fcPosNormal | fcPosInf;
-      FPClassTest ClassesLE = fcNegative | fcPosZero | fcPosSubnormal;
-      if (IsDenormalRHS)
-        ClassesGE |= fcPosSubnormal;
-      else
-        ClassesLE |= fcPosNormal;
-
-      if (IsFabs) {
-        ClassesGE = llvm::inverse_fabs(ClassesGE);
-        ClassesLE = llvm::inverse_fabs(ClassesLE);
-      }
-
-      switch (Pred) {
-      case FCmpInst::FCMP_OGT:
-      case FCmpInst::FCMP_OGE:
-        return {Src, ClassesGE, ~ClassesGE | RHSClass};
-      case FCmpInst::FCMP_UGT:
-      case FCmpInst::FCMP_UGE:
-        return {Src, ClassesGE | fcNan, ~(ClassesGE | fcNan) | RHSClass};
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_OLE:
-        return {Src, ClassesLE, ~ClassesLE | RHSClass};
-      case FCmpInst::FCMP_ULT:
-      case FCmpInst::FCMP_ULE:
-        return {Src, ClassesLE | fcNan, ~(ClassesLE | fcNan) | RHSClass};
-      default:
-        break;
-      }
-    }
-
-    return {Invalid, fcAllFlags, fcAllFlags};
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   const APFloat &ConstRHS, bool LookThroughSrc) {
-    // We can refine checks against smallest normal / largest denormal to an
-    // exact class test.
-    if (!ConstRHS.isNegative() && ConstRHS.isSmallestNormalized()) {
-      ValueRefT Src = LHS;
-      const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
-
-      FPClassTest Mask;
-      // Match pattern that's used in __builtin_isnormal.
-      switch (Pred) {
-      case FCmpInst::FCMP_OLT:
-      case FCmpInst::FCMP_UGE: {
-        // fcmp olt x, smallest_normal ->
-        // fcNegInf|fcNegNormal|fcSubnormal|fcZero fcmp olt fabs(x),
-        // smallest_normal -> fcSubnormal|fcZero fcmp uge x, smallest_normal ->
-        // fcNan|fcPosNormal|fcPosInf fcmp uge fabs(x), smallest_normal ->
-        // ~(fcSubnormal|fcZero)
-        Mask = fcZero | fcSubnormal;
-        if (!IsFabs)
-          Mask |= fcNegNormal | fcNegInf;
-
-        break;
-      }
-      case FCmpInst::FCMP_OGE:
-      case FCmpInst::FCMP_ULT: {
-        // fcmp oge x, smallest_normal -> fcPosNormal | fcPosInf
-        // fcmp oge fabs(x), smallest_normal -> fcInf | fcNormal
-        // fcmp ult x, smallest_normal -> ~(fcPosNormal | fcPosInf)
-        // fcmp ult fabs(x), smallest_normal -> ~(fcInf | fcNormal)
-        Mask = fcPosInf | fcPosNormal;
-        if (IsFabs)
-          Mask |= fcNegInf | fcNegNormal;
-        break;
-      }
-      default:
-        return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(),
-                                LookThroughSrc);
-      }
-
-      // Invert the comparison for the unordered cases.
-      if (FCmpInst::isUnordered(Pred))
-        Mask = ~Mask;
-
-      return exactClass(Src, Mask);
-    }
-
-    return fcmpImpliesClass(Pred, F, LHS, ConstRHS.classify(), LookThroughSrc);
-  }
-
-  static std::tuple<ValueRefT, FPClassTest, FPClassTest>
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-                   ValueRefT RHS, bool LookThroughSrc) {
-    std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
-    if (!ConstRHS)
-      return {Invalid, fcAllFlags, fcAllFlags};
-
-    // TODO: Just call computeKnownFPClass for RHS to handle non-constants.
-    return fcmpImpliesClass(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-};
-
-} // namespace llvm
-
-#endif // LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
diff --git a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h b/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
deleted file mode 100644
index 96fdbf48d8b43..0000000000000
--- a/llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- llvm/Analysis/FloatingPointPredicateUtils.h ------------*- C++ -*---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ANALYSIS_FLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/GenericFloatingPointPredicateUtils.h"
-#include "llvm/IR/SSAContext.h"
-
-namespace llvm {
-
-using FloatingPointPredicateUtils =
-    GenericFloatingPointPredicateUtils<SSAContext>;
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                Value *RHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, RHS,
-                                                      LookThroughSrc = true);
-}
-
-/// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-/// same result as an fcmp with the given operands.
-///
-/// If \p LookThroughSrc is true, consider the input value when computing the
-/// mask.
-///
-/// If \p LookThroughSrc is false, ignore the source value (i.e. the first pair
-/// element will always be LHS.
-inline std::pair<Value *, FPClassTest>
-fcmpToClassTest(FCmpInst::Predicate Pred, const Function &F, Value *LHS,
-                const APFloat *ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpToClassTest(Pred, F, LHS, *ConstRHS,
-                                                      LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 FPClassTest RHSClass, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, RHSClass,
-                                                       LookThroughSrc);
-}
-
-inline std::tuple<Value *, FPClassTest, FPClassTest>
-fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
-                 const APFloat &ConstRHS, bool LookThroughSrc = true) {
-  return FloatingPointPredicateUtils::fcmpImpliesClass(Pred, F, LHS, Const...
[truncated]

@tgymnich
Copy link
Member Author

alternatively this should fix the breakage without reverting: #141260.

Again sorry for the breakage this has caused.

Copy link
Collaborator

@cachemeifyoucan cachemeifyoucan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick reaction!

@tgymnich tgymnich force-pushed the tim/revert-fp-predicate-utils branch from 53755fa to 702b736 Compare May 23, 2025 17:30
@tgymnich tgymnich changed the title Revert add GenericFloatingPointPredicateUtils #140254 #141257 Fix GenericFloatingPointPredicateUtils 2 May 23, 2025
@tgymnich
Copy link
Member Author

Turing this into a fix rather than a revert. Since the revert would break stuff depending on this...

@tgymnich tgymnich changed the title Fix GenericFloatingPointPredicateUtils 2 Fix GenericFloatingPointPredicateUtils May 23, 2025
@cachemeifyoucan
Copy link
Collaborator

I did a quick test and the new location for header and implementation works for module layering. Thanks

@tgymnich tgymnich merged commit dc8f2f0 into llvm:main May 23, 2025
16 of 23 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 23, 2025

LLVM Buildbot has detected a new failure on builder sanitizer-aarch64-linux-bootstrap-hwasan running on sanitizer-buildbot12 while building llvm at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/55/builds/11777

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 87402 tests, 72 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 
FAIL: LLVM :: ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s (52997 of 87402)
******************** TEST 'LLVM :: ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
rm -rf /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp && mkdir -p /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp # RUN: at line 1
+ rm -rf /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp
+ mkdir -p /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp
/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj    -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/Inputs/MachO_test_harness_test.s # RUN: at line 2
+ /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/Inputs/MachO_test_harness_test.s
/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj    -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s # RUN: at line 4
+ /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s
not /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-jitlink -noexec -check /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o     -harness /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o # RUN: at line 6
+ not /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-jitlink -noexec -check /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o -harness /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o
llvm-jitlink error: Symbols not found: [ _unresolvable_external, _used_unresolved_external ]
llvm-jitlink error: In main, failed to materialize { _anchor_test_case_pointers }, due to unsatisfied dependencies { (main, { _private_func_to_interpose_as_seen_by_test, _public_func_to_interpose_as_seen_by_test }) } (dependencies removed or in error state)
libc++abi: Pure virtual function called!
error: Aborted

--

********************
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
Slowest Tests:
--------------------------------------------------------------------------
61.40s: Clang :: Driver/fsanitize.c
43.13s: Clang :: Preprocessor/riscv-target-features.c
39.58s: Clang :: Driver/arm-cortex-cpus-2.c
38.62s: Clang :: Driver/arm-cortex-cpus-1.c
36.18s: LLVM :: CodeGen/AMDGPU/sched-group-barrier-pipeline-solver.mir
35.09s: Clang :: OpenMP/target_defaultmap_codegen_01.cpp
33.35s: Clang :: OpenMP/target_update_codegen.cpp
31.22s: LLVM :: CodeGen/RISCV/attributes.ll
30.79s: Clang :: Preprocessor/arm-target-features.c
30.08s: Clang :: Preprocessor/aarch64-target-features.c
29.06s: LLVM :: CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll
25.81s: Clang :: Driver/linux-ld.c
25.27s: Clang :: Driver/clang_f_opts.c
Step 11 (stage2/hwasan check) failure: stage2/hwasan check (failure)
...
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 87402 tests, 72 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 
FAIL: LLVM :: ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s (52997 of 87402)
******************** TEST 'LLVM :: ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
rm -rf /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp && mkdir -p /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp # RUN: at line 1
+ rm -rf /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp
+ mkdir -p /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp
/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj    -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/Inputs/MachO_test_harness_test.s # RUN: at line 2
+ /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/Inputs/MachO_test_harness_test.s
/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj    -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s # RUN: at line 4
+ /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s
not /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-jitlink -noexec -check /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o     -harness /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o # RUN: at line 6
+ not /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/llvm-jitlink -noexec -check /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/test/ExecutionEngine/JITLink/x86-64/MachO_test_harness_harness.s /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/file_to_test.o -harness /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/test/ExecutionEngine/JITLink/x86-64/Output/MachO_test_harness_harness.s.tmp/test_harness.o
llvm-jitlink error: Symbols not found: [ _unresolvable_external, _used_unresolved_external ]
llvm-jitlink error: In main, failed to materialize { _anchor_test_case_pointers }, due to unsatisfied dependencies { (main, { _private_func_to_interpose_as_seen_by_test, _public_func_to_interpose_as_seen_by_test }) } (dependencies removed or in error state)
libc++abi: Pure virtual function called!
error: Aborted

--

********************
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
Slowest Tests:
--------------------------------------------------------------------------
61.40s: Clang :: Driver/fsanitize.c
43.13s: Clang :: Preprocessor/riscv-target-features.c
39.58s: Clang :: Driver/arm-cortex-cpus-2.c
38.62s: Clang :: Driver/arm-cortex-cpus-1.c
36.18s: LLVM :: CodeGen/AMDGPU/sched-group-barrier-pipeline-solver.mir
35.09s: Clang :: OpenMP/target_defaultmap_codegen_01.cpp
33.35s: Clang :: OpenMP/target_update_codegen.cpp
31.22s: LLVM :: CodeGen/RISCV/attributes.ll
30.79s: Clang :: Preprocessor/arm-target-features.c
30.08s: Clang :: Preprocessor/aarch64-target-features.c
29.06s: LLVM :: CodeGen/AMDGPU/amdgcn.bitcast.1024bit.ll
25.81s: Clang :: Driver/linux-ld.c
25.27s: Clang :: Driver/clang_f_opts.c

@tgymnich tgymnich deleted the tim/revert-fp-predicate-utils branch May 23, 2025 21:13
@cachemeifyoucan
Copy link
Collaborator

Bot is hitting a different error now: https://green.lab.llvm.org/job/llvm.org/job/clang-stage2-Rthinlto/769/console

22:32:01 
 /Users/ec2-user/jenkins/workspace/llvm.org/clang-stage2-Rthinlto/llvm-project/llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp:23:37: error: explicit specialization of 'queryDenormalMode' after instantiation
22:32:01     23 | MachineFloatingPointPredicateUtils::queryDenormalMode(const MachineFunction &MF,
22:32:01        |                                     ^
22:32:01  /Users/ec2-user/jenkins/workspace/llvm.org/clang-stage2-Rthinlto/llvm-project/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h:132:27: note: implicit instantiation first required here
22:32:01    132 |       DenormalMode Mode = queryDenormalMode(F, LHS);
22:32:01        |                           ^
22:32:01  /Users/ec2-user/jenkins/workspace/llvm.org/clang-stage2-Rthinlto/llvm-project/llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp:31:42: error: explicit specialization of 'lookThroughFAbs' after instantiation
22:32:01     31 | bool MachineFloatingPointPredicateUtils::lookThroughFAbs(
22:32:01        |                                          ^
22:32:01  /Users/ec2-user/jenkins/workspace/llvm.org/clang-stage2-Rthinlto/llvm-project/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h:421:45: note: implicit instantiation first required here
22:32:01    421 |       const bool IsFabs = LookThroughSrc && lookThroughFAbs(F, LHS, Src);
22:32:01        |                                             ^
22:32:01  /Users/ec2-user/jenkins/workspace/llvm.org/clang-stage2-Rthinlto/llvm-project/llvm/lib/CodeGen/GlobalISel/MachineFloatingPointPredicateUtils.cpp:38:60: error: explicit specialization of 'matchConstantFloat' after instantiation
22:32:01     38 | std::optional<APFloat> MachineFloatingPointPredicateUtils::matchConstantFloat(
22:32:01        |                                                            ^
22:32:01  /Users/ec2-user/jenkins/workspace/llvm.org/clang-stage2-Rthinlto/llvm-project/llvm/include/llvm/IR/GenericFloatingPointPredicateUtils.h:468:39: note: implicit instantiation first required here
22:32:01    468 |     std::optional<APFloat> ConstRHS = matchConstantFloat(F, RHS);
22:32:01        |                                       ^
22:32:01  3 errors generated.

@tgymnich
Copy link
Member Author

@cachemeifyoucan fix: #141368

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:adt llvm:analysis Includes value tracking, cost tables and constant folding llvm:globalisel llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:ir llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants